/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.rbac.service.menu.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.constants.tree.NodeType;
import com.je.common.base.exception.PlatformException;
import com.je.common.base.exception.PlatformExceptionEnum;
import com.je.common.base.mapper.query.Condition;
import com.je.common.base.mapper.query.ConditionEnum;
import com.je.common.base.mapper.query.NativeQuery;
import com.je.common.base.mapper.query.Query;
import com.je.common.base.result.BaseRespResult;
import com.je.common.base.result.DirectJsonResult;
import com.je.common.base.service.CommonService;
import com.je.common.base.service.MetaResourceService;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.service.rpc.SystemSettingRpcService;
import com.je.common.base.spring.SpringContextHolder;
import com.je.common.base.util.JEUUID;
import com.je.common.base.util.ReflectionUtils;
import com.je.common.base.util.SecurityUserHolder;
import com.je.common.base.util.StringUtil;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.rpc.develop.DevelopLogRpcService;
import com.je.meta.rpc.framework.product.ProductRpcService;
import com.je.meta.rpc.func.MetaFuncRpcService;
import com.je.meta.rpc.setting.MetaSystemSettingRpcService;
import com.je.rbac.cache.AccountPermissionCache;
import com.je.rbac.cache.AccountProductCache;
import com.je.rbac.cache.FuncPermissionCache;
import com.je.rbac.exception.MenuException;
import com.je.rbac.rpc.PermissionRpcService;
import com.je.rbac.service.menu.MenuService;
import com.je.rbac.service.permission.template.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class MenuServiceImpl implements MenuService {

    private static Logger logger = LoggerFactory.getLogger(MenuServiceImpl.class);

    private static final String SAAS_PRODUCT_TOP_MENU = "saasTopMenu";

    private static final String SAAS_TENANT_INSTALLED_PRODUCT_KEY = "saasTenantInstalledProduct";

    /**
     * 改模块对应的表
     */
    private static final String TABLECODE = "JE_CORE_MENU";
    /**
     * 是否记录日志CODE
     */
    private static final String JE_SYS_DEVELOPLOG = "JE_SYS_DEVELOPLOG";
    /**
     * 菜单类型为模块或者菜单
     */
    private static final String MENUTYPE = "MENU";
    /**
     * 根节点ID
     */
    private static final String ROOT = "ROOT";
    /**
     * 产品Code
     */
    private static final String SY_PRODUCT_CODE = "SY_PRODUCT_CODE";
    /**
     * 产品ID
     */
    private static final String SY_PRODUCT_ID = "SY_PRODUCT_ID";
    /**
     * 产品NAME
     */
    private static final String SY_PRODUCT_NAME = "SY_PRODUCT_NAME";

    @Autowired
    private MetaService metaService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private BeanService beanService;
    @Autowired
    private DevelopLogRpcService developLogRpcService;
    @Autowired
    private SystemSettingRpcService systemSettingRpcService;
    @Autowired
    private MetaSystemSettingRpcService metaSystemSettingRpcService;
    @Autowired
    private ProductRpcService productRpcService;
    @Autowired
    private PermissionRpcService permissionRpcService;
    @Autowired
    private TopMenuDataService topMenuDataService;
    @Autowired
    private PcMenuDataService pcMenuDataService;
    @Autowired
    private PcFuncBaseService pcFuncBaseService;
    @Autowired
    private PcFuncButtonService pcFuncButtonService;
    @Autowired
    private PcPluginBaseService pcPluginBaseService;
    @Autowired
    private PcSubFuncRelationService pcSubFuncRelationService;
    @Autowired
    private MetaFuncRpcService metaFuncRpcService;
    @Autowired
    private AccountPermissionCache accountPermissionCache;
    @Autowired
    private AccountProductCache accountProductCache;
    @Autowired
    private FuncPermissionCache funcPermissionCache;
    @Autowired
    private MenuService menuService;
    @Autowired
    private MetaResourceService metaResourceService;
    @Autowired
    private RedisTemplate redisTemplate;


    private List<String> buildTenantTopMenu(String tenantId) {
        Object tenantProduct = redisTemplate.opsForHash().get(SAAS_TENANT_INSTALLED_PRODUCT_KEY, tenantId);
        List<String> tenantTopMenuList = null;
        if (tenantProduct != null) {
            List<String> tenantProductList = (List<String>) tenantProduct;
            List<Object> valueObjList = redisTemplate.opsForHash().multiGet(SAAS_PRODUCT_TOP_MENU, tenantProductList);
            if (valueObjList != null && !valueObjList.isEmpty()) {
                tenantTopMenuList = new ArrayList<>();
                for (Object value : valueObjList) {
                    if (value != null) {
                        tenantTopMenuList.addAll((List) value);
                    }
                }
            }
        }
        return tenantTopMenuList;
    }

    @Override
    public List<Map<String, Object>> loadHomeTopMenus(String departmentId, String accountId, String tenantId, String plan) {

        List<String> accountTopMenuPermissions = permissionRpcService.findAccountTopMenuPermissions(departmentId, accountId, tenantId);
        List<String> accountMenuPermissions = permissionRpcService.findAccountMenuPermissions(departmentId, accountId, tenantId);

        ConditionsWrapper topMenuWrapper = ConditionsWrapper.builder();
        topMenuWrapper.eq("SY_STATUS", "1");

        //不是system租户，则返回租户安装的顶部菜单
        if (!Strings.isNullOrEmpty(tenantId) && !"system".equals(tenantId)) {
            List<String> tenantTopMenuList = buildTenantTopMenu(tenantId);
            topMenuWrapper.in("JE_RBAC_HEADMENU_ID", tenantTopMenuList);
        }

        if (!Strings.isNullOrEmpty(plan)) {
            DynaBean planBean = metaResourceService.selectOneByNativeQuery("JE_CORE_SETPLAN",
                    NativeQuery.build().eq("JE_SYS_PATHSCHEME", plan));
            String topMenuId = planBean.getStr("SETPLAN_ASSOCIATE_TOP_MENU_ID");
            String isAssociateAllTopMenu = planBean.getStr("SETPLAN_ASSOCIATE_ALL_TOP_MENU", "1");
            if (!Strings.isNullOrEmpty(topMenuId) && !isAssociateAllTopMenu.equals("1")) {
                topMenuWrapper.in("JE_RBAC_HEADMENU_ID", Splitter.on(",").splitToList(topMenuId));
            }
        }

        topMenuWrapper.orderByAsc("SY_ORDERINDEX");
        List<DynaBean> topMenuBeanList = metaService.select("JE_RBAC_HEADMENU", topMenuWrapper);

        List<Map<String, Object>> relationMenus = metaService.selectSql(ConditionsWrapper.builder()
                .table("JE_CORE_MENU").apply(" AND SY_PARENT='ROOT' ").orderByAsc("SY_ORDERINDEX"));

        List<Map<String, Object>> permedList = new ArrayList<>();
        List<Map<String, Object>> relations;
        for (DynaBean eachBean : topMenuBeanList) {
            if ("0".equals(eachBean.getStr("HEADMENU_PUBLIC_CODE")) && !accountTopMenuPermissions.contains(topMenuDataService.formatTopMenuShowTemplate(eachBean.getStr("JE_RBAC_HEADMENU_ID")))) {
                continue;
            }
            relations = new ArrayList<>();
            for (Map<String, Object> eachRelationMenu : relationMenus) {
                if (eachRelationMenu.get("MENU_LINK_TOPMENU_ID") == null) {
                    continue;
                }
                if (eachRelationMenu.get("MENU_LINK_TOPMENU_ID").toString().indexOf(eachBean.getStr("JE_RBAC_HEADMENU_ID")) >= 0
                        && accountMenuPermissions.contains(pcMenuDataService.formatMenuDataShowTemplate(eachRelationMenu.get("JE_CORE_MENU_ID").toString()))) {
                    relations.add(eachRelationMenu);
                }
            }
            eachBean.set("relations", relations);
            permedList.add(eachBean.getValues());
        }

        return permedList;
    }

    @Override
    public JSONTreeNode loadHomeMenus(String departmentId, String accountId, String tenantId, String plan) {
        List<String> menuPermissionList = permissionRpcService.findAccountMenuPermissions(departmentId, accountId, tenantId);
        ConditionsWrapper menuWrapper = ConditionsWrapper.builder();
        menuWrapper.table(TABLECODE);
        menuWrapper.eq("SY_STATUS", "1");
        //根据方案，找到顶部菜单，根据顶部菜单中的一级模块like所有菜单
        DynaBean planBean = metaResourceService.selectOneByNativeQuery("JE_CORE_SETPLAN", NativeQuery.build().eq("JE_SYS_PATHSCHEME", plan));
        String topMenuId = planBean.getStr("SETPLAN_ASSOCIATE_TOP_MENU_ID");
        String isAssociateAllTopMenu = planBean.getStr("SETPLAN_ASSOCIATE_ALL_TOP_MENU", "1");
        if (!Strings.isNullOrEmpty(topMenuId) && !isAssociateAllTopMenu.equals("1")) {
            List<DynaBean> headmenu_relation = metaService.select("JE_RBAC_HEADMENU_RELATION",
                    ConditionsWrapper.builder().in("JE_RBAC_HEADMENU_ID", Splitter.on(",").splitToList(topMenuId)), "RELATION_MENUMODULE_ID");
            menuWrapper.and(inWrapper -> {
                for (int i = 0; i < headmenu_relation.size(); i++) {
                    if (i > 0) {
                        inWrapper.or();
                    }
                    inWrapper.like("SY_PATH", headmenu_relation.get(i).getStr("RELATION_MENUMODULE_ID"));
                }
            });
        }
        menuWrapper.or().eq("JE_CORE_MENU_ID", "ROOT");
        menuWrapper.orderByAsc("SY_TREEORDERINDEX");
        List<Map<String, Object>> menuBeanList = metaService.selectSql(menuWrapper);
        List<JSONTreeNode> nodeList = new ArrayList<>();
        JSONTreeNode template = beanService.getTreeTemplate(TABLECODE);
        //遍历结果构建树形节点对象
        menuBeanList.forEach(record -> {
            if (!menuPermissionList.contains(pcMenuDataService.formatMenuDataShowTemplate(record.get("JE_CORE_MENU_ID").toString()))) {
                return;
            }
            //主键
            String nodeId = (String) record.get(template.getId());
            JSONTreeNode node = new JSONTreeNode();
            node.setId(nodeId);
            node.setText((String) record.get(template.getText()));
            //编码
            node.setCode((String) record.get(template.getCode()));
            //父节点
            node.setParent((String) record.get(template.getParent()));
            //节点信息
            if (StringUtil.isNotEmpty(template.getNodeInfo())) {
                node.setNodeInfo(StringUtil.getClobValue(record.get(template.getNodeInfo())));
            }
            //节点信息类型
            if (StringUtil.isNotEmpty(template.getNodeInfoType())) {
                node.setNodeInfoType(record.get(template.getNodeInfoType()) + "");
            }
            //是否叶子
            if (StringUtil.isNotEmpty(template.getNodeType())) {
                node.setLeaf(NodeType.LEAF.equalsIgnoreCase(record.get(template.getNodeType()) + ""));
                node.setNodeType(record.get(template.getNodeType()) + "");
            }
            if (StringUtil.isNotEmpty(template.getLayer())) {
                node.setLayer(record.get(template.getLayer()) + "");
            }
            //图标图片地址
            if (StringUtil.isNotEmpty(template.getIcon())) {
                node.setIcon(record.get(template.getIcon()) + "");
            }
            //图标样式
            if (StringUtil.isNotEmpty(template.getIconColor())) {
                node.setIconColor(record.get(template.getIconColor()) + "");
            }
            //是否禁用
            if (StringUtil.isNotEmpty(template.getDisabled())) {
                node.setDisabled(record.get(template.getDisabled()) + "");
            } else {
                node.setDisabled("0");
            }
            //树形路径
            if (StringUtil.isNotEmpty(template.getNodePath())) {
                node.setNodePath(record.get(template.getNodePath()) + "");
            }
            //描述
            if (StringUtil.isNotEmpty(template.getDescription())) {
                node.setDescription(StringUtil.getClobValue(record.get(template.getDescription())));
            }
            //排序
            if (StringUtil.isNotEmpty(template.getOrderIndex())) {
                node.setOrderIndex(record.get(template.getOrderIndex()) + "");
            }
            if (StringUtil.isNotEmpty(template.getTreeOrderIndex())) {
                node.setTreeOrderIndex(record.get(template.getTreeOrderIndex()) + "");
            }
            node.setBean(record);
            nodeList.add(node);
        });

        JSONTreeNode rootNode = commonService.buildJSONNewTree(nodeList, "ROOT");

        return rootNode;
    }

    @Override
    public List<Map<String, Object>> getQuickMenu(String userId) {
        long count = metaService.countBySql("select count(*) from JE_CORE_KJMENU where KJMENU_YHUD = {0}", userId);
        List<Map<String, Object>> result;
        if (count > 0) {
            result = metaService.selectSql("select MENU_NODEINFO from je_core_menu where SY_STATUS='1' AND MENU_NODEINFOTYPE IN('MT') AND JE_CORE_MENU_ID in (select KJMENU_CDID from JE_CORE_KJMENU where KJMENU_YHUD={0})", userId);
        } else {
            result = metaService.selectSql("select MENU_NODEINFO from je_core_menu where SY_STATUS='1' AND MENU_NODEINFOTYPE IN('MT') AND MENU_QUICKSTART='1'");
        }
        return result;
    }

    @Override
    public DynaBean doSave(DynaBean dynaBean) {
        //buildProductInfo(dynaBean);
        //添加树形排序和生成主键
        /*String sql = "SELECT COUNT(*) FROM JE_CORE_MENU WHERE SY_PARENT={0}";
        long count = metaService.countBySql(sql, dynaBean.getStr("SY_PARENT", "ROOT")) + 1;
        dynaBean.set("SY_ORDERINDEX", count);*/
        if (StringUtil.isEmpty(dynaBean.getStr("MENU_ICON"))) {
            dynaBean.setStr("MENU_ICON", "fal fa-poll-h");
        }
        dynaBean.set("JE_CORE_MENU_ID", JEUUID.uuid());
        String tableCode = dynaBean.getTableCode();
        if (StringUtil.isEmpty(tableCode)) {
            dynaBean.setStr(BeanService.KEY_TABLE_CODE, "JE_CORE_MENU");
        }
        if (StringUtil.isEmpty(dynaBean.getStr("SY_PATH"))) {
            DynaBean parentInfo = metaService.selectOneByPk("JE_CORE_MENU", dynaBean.getStr("SY_PARENT"));
            dynaBean.setStr("SY_PATH", parentInfo.getStr("SY_PATH") + "/" + dynaBean.getStr("JE_CORE_MENU_ID"));
            dynaBean.set("SY_PARENTPATH", parentInfo.getStr("SY_PATH"));
        }
        commonService.generateTreeOrderIndex(dynaBean);

        if (isLog()) {
            developLogRpcService.doDevelopLog("CREATE", "创建", "MENU", "菜单", dynaBean.getStr("MENU_MENUNAME"), dynaBean.getStr("MENU_CODE"), dynaBean.getStr("JE_CORE_MENU_ID"), dynaBean.getStr("SY_PRODUCT_ID"));
        }
        return dynaBean;
    }

    @Override
    public JSONTreeNode getTree(Query query, String node) {
        JSONTreeNode template = beanService.getTreeTemplate(TABLECODE);
        List<JSONTreeNode> jsonTreeNodeList = commonService.loadTreeNodeList(node, TABLECODE, template, query);
        //字体图标
        JSONTreeNode rootNode = commonService.buildJSONNewTree(jsonTreeNodeList, node);
        return rootNode;
    }


    @Override
    public BaseRespResult menuMove(String menuId, String toModuleId) {
        DynaBean menu = metaService.selectOneByPk("JE_CORE_MENU", menuId);
        DynaBean toModuleMenu = metaService.selectOneByPk("JE_CORE_MENU", toModuleId);
        String toModuleMenuType = toModuleMenu.getStr("MENU_NODEINFOTYPE");
        if ((Strings.isNullOrEmpty(toModuleMenuType) || !toModuleMenuType.equals(MENUTYPE)) && !toModuleId.equals(ROOT)) {
            return BaseRespResult.errorResult("请选择菜单类型为“模块”或者“菜单”类型的菜单！");
        }
        String fromId = menu.getStr("SY_PARENT");
        String fromPath = menu.getStr("SY_PATH");
        //设置父级id ,当前path ,父级path
        String SY_PARENT = toModuleId;
        String SY_PATH = toModuleMenu.getStr("SY_PATH") + "/" + menu.getPkValue();
        String SY_PARENTPATH = toModuleMenu.getStr("SY_PARENT");
        menu.set("SY_PARENTPATH", SY_PARENTPATH);
        menu.set("SY_PATH", SY_PATH);
        menu.set("SY_PARENT", SY_PARENT);
        //更新当前节点下所有孩子的路径信息
        getUpdateChildSql(fromPath, menu);
        metaService.update(menu);
        //根据树形属性，查看字节的信息，如果有多个类型为LEAF，普通为GENERAL
        commonService.updateTreePanent4NodeType("JE_CORE_MENU", fromId);
        commonService.updateTreePanent4NodeType("JE_CORE_MENU", toModuleId);
        //更新权限 todo 移动时考虑授权

        //更新平台功能
        metaService.executeSql("UPDATE JE_CORE_MENU SET SY_ORDERINDEX=-10 WHERE JE_CORE_MENU_ID='5a675576-c061-4282-91d7-6b5c1158f238'");
        //更新系统管理
        metaService.executeSql("UPDATE JE_CORE_MENU SET SY_ORDERINDEX=100 WHERE JE_CORE_MENU_ID='9865c50d-361b-4139-b775-78678ad42641'");
        return BaseRespResult.successResult("转移成功！");
    }

    /**
     * 获取当前节点下所有孩子的路径信息 sql
     *
     * @param fromPath          转移前的路径
     * @param afterTransferMenu 转移后的菜单bean
     * @return
     */
    private void getUpdateChildSql(String fromPath, DynaBean afterTransferMenu) {
        StringBuffer stringBuffer = new StringBuffer("");
        List<DynaBean> list = metaService.select("JE_CORE_MENU", ConditionsWrapper.builder().like("SY_PARENTPATH", fromPath));
        for (DynaBean menu : list) {
            String SY_PARENTPATH = menu.getStr("SY_PARENTPATH").replace(fromPath, afterTransferMenu.getStr("SY_PATH"));
            String SY_PAT = menu.getStr("SY_PATH").replace(fromPath, afterTransferMenu.getStr("SY_PATH"));
            stringBuffer.append(String.format("UPDATE JE_CORE_MENU SET SY_PARENTPATH='%s',SY_PATH='%s' WHERE JE_CORE_MENU_ID = '%s';", SY_PARENTPATH, SY_PAT, menu.getPkValue()));
        }
        if (stringBuffer.length() > 0) {
            metaService.executeSql(stringBuffer.toString());
        }
    }

    private String getFuncCode(DynaBean funcBean) {
        if (funcBean == null) {
            return null;
        }
        return funcBean.getStr("FUNCINFO_FUNCCODE");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int doRemove(String menuIds) {
        List<String> menuIdList = Splitter.on(",").splitToList(menuIds);
        List<DynaBean> menus = metaService.select("JE_CORE_MENU", ConditionsWrapper.builder().in("JE_CORE_MENU_ID", menuIdList));
        List<String> funcCodeList = new ArrayList<>();
        List<String> permCodeList = new ArrayList<>();
        for (DynaBean menu : menus) {
            if (isLog()) {
                developLogRpcService.doDevelopLog("DELETE", "删除", "MENU", "菜单", menu.getStr("MENU_MENUNAME"), menu.getStr("MENU_CODE"), menu.getStr("JE_CORE_MENU_ID"), menu.getStr("SY_PRODUCT_ID"));
            }
            if ("MT".equals(menu.getStr("MENU_NODEINFOTYPE"))) {
                funcCodeList.add(menu.getStr("MENU_NODEINFO"));
            } else {
                if (!Strings.isNullOrEmpty(menu.getStr("MENU_NODEINFO"))) {
                    permCodeList.add(pcPluginBaseService.formatPcPluginShowTemplate(menu.getStr("MENU_NODEINFO")));
                    permCodeList.add(pcPluginBaseService.formatPcPluginConfigTemplate(menu.getStr("MENU_NODEINFO")));
                }
            }
            permCodeList.add(pcMenuDataService.formatMenuDataShowTemplate(menu.getStr("JE_CORE_MENU_ID")));
            permCodeList.add(pcMenuDataService.formatMenuDataUpdateTemplate(menu.getStr("JE_CORE_MENU_ID")));
            permCodeList.add(pcMenuDataService.formatMenuDataDeleteTemplate(menu.getStr("JE_CORE_MENU_ID")));

            //级联删除顶部菜单关联表的菜单数据
            if (!Strings.isNullOrEmpty(menu.getStr("MENU_LINK_TOPMENU_ID"))) {
                menuService.doRemoveHeadMenuRelation(menu.getStr("JE_CORE_MENU_ID"), menu.getStr("MENU_LINK_TOPMENU_ID"));
            }
        }

        List<String> permIdList = new ArrayList<>();
        //功能
        Map<String, List<DynaBean>> funcResult = metaFuncRpcService.findPermedFuncsAndChildFuncsWithButtonsByFuncCodes(funcCodeList);
        List<DynaBean> mainFuncList = funcResult.get("main");
        //子功能
        List<DynaBean> childFuncRelationList = funcResult.get("child");
        //功能按钮
        List<DynaBean> funcButtonList = funcResult.get("button") == null ? new ArrayList<>() : funcResult.get("button");
        //子功能所属功能
        List<String> subFuncRelationIdList = new ArrayList<>();
        if (childFuncRelationList != null && !childFuncRelationList.isEmpty()) {
            childFuncRelationList.forEach(each -> {
                subFuncRelationIdList.add(each.getStr("JE_CORE_FUNCRELATION_ID"));
            });
        }
        Map<String, DynaBean> funcIdCodeMap = metaFuncRpcService.findSubFuncParentFuncInfos(subFuncRelationIdList);

        for (DynaBean eachFuncBean : mainFuncList) {
            //功能权限
            permCodeList.add(pcFuncBaseService.formatPcFuncShowTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE")));
            permCodeList.add(pcFuncBaseService.formatPcFuncConfigTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE")));
            permCodeList.add(pcFuncBaseService.formatPcFuncUpdateTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE")));
            permCodeList.add(pcFuncBaseService.formatPcFuncDeleteTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE")));
            //设置功能按钮的权限
            for (DynaBean eachButtonBean : funcButtonList) {
                if (eachFuncBean.getStr("JE_CORE_FUNCINFO_ID").equals(eachButtonBean.getStr("RESOURCEBUTTON_FUNCINFO_ID"))) {
                    permCodeList.add(pcFuncButtonService.formatPcFuncButtonShowTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE"), eachButtonBean.getStr("RESOURCEBUTTON_CODE")));
                    permCodeList.add(pcFuncButtonService.formatPcFuncButtonUpdateTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE"), eachButtonBean.getStr("RESOURCEBUTTON_CODE")));
                    permCodeList.add(pcFuncButtonService.formatPcFuncButtonDeleteTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE"), eachButtonBean.getStr("RESOURCEBUTTON_CODE")));
                }
            }
        }

        //子功能
        for (int i = 0; childFuncRelationList != null && !childFuncRelationList.isEmpty() && i < childFuncRelationList.size(); i++) {
            //此处设置子功能展示权限，用于check校验
            if ("func".equals(childFuncRelationList.get(i).getStr("FUNCRELATION_RELYONTYPE"))) {
                permCodeList.add(pcSubFuncRelationService.formatPcSubFuncRelationShowTemplate(getFuncCode(funcIdCodeMap.get(childFuncRelationList.get(i).getStr("JE_CORE_FUNCRELATION_ID"))), childFuncRelationList.get(i).getStr("FUNCRELATION_CODE")));
                //设置功能按钮的功能属性，用于构建树形
                for (DynaBean eachButtonBean : funcButtonList) {
                    if (childFuncRelationList.get(i).getStr("FUNCRELATION_FUNCID").equals(eachButtonBean.getStr("RESOURCEBUTTON_FUNCINFO_ID"))) {
                        permCodeList.add(pcFuncButtonService.formatPcFuncButtonShowTemplate(childFuncRelationList.get(i).getStr("FUNCRELATION_CODE"),
                                eachButtonBean.getStr("RESOURCEBUTTON_CODE")));
                    }
                }
            } else {
                childFuncRelationList.get(i).set("PERM_SHOW", pcSubFuncRelationService.formatPcSubFuncRelationShowTemplate(getFuncCode(funcIdCodeMap.get(childFuncRelationList.get(i).getStr("JE_CORE_FUNCRELATION_ID"))), childFuncRelationList.get(i).getStr("FUNCRELATION_CODE")));
            }
        }

        if (!permCodeList.isEmpty()) {
            List<DynaBean> permissionList = metaService.select("JE_RBAC_PERM", ConditionsWrapper.builder()
                    .in("PERM_CODE", permCodeList));
            for (DynaBean eachPluginPermission : permissionList) {
                if (!permIdList.contains(eachPluginPermission.getStr("JE_RBAC_PERM_ID"))) {
                    permIdList.add(eachPluginPermission.getStr("JE_RBAC_PERM_ID"));
                }
            }
        }

        if (!permIdList.isEmpty()) {
            metaService.delete("JE_RBAC_ROLEPERM", ConditionsWrapper.builder().in("JE_RBAC_PERM_ID", permIdList));
            metaService.delete("JE_RBAC_DEPTPERM", ConditionsWrapper.builder().in("JE_RBAC_PERM_ID", permIdList));
            metaService.delete("JE_RBAC_USERPERM", ConditionsWrapper.builder().in("JE_RBAC_PERM_ID", permIdList));
            metaService.delete("JE_RBAC_PERMGROUPPERM", ConditionsWrapper.builder().in("JE_RBAC_PERM_ID", permIdList));
            metaService.delete("JE_RBAC_ORGPERM", ConditionsWrapper.builder().in("JE_RBAC_PERM_ID", permIdList));
        }


        accountPermissionCache.clear();
        accountProductCache.clear();
        funcPermissionCache.clear();
        return metaService.delete("JE_CORE_MENU", ConditionsWrapper.builder().in("JE_CORE_MENU_ID", Splitter.on(",").splitToList(menuIds)));
    }

    @Override
    public JSONObject loadBadge(String funcCode) {
        List<DynaBean> list = new ArrayList<DynaBean>();
        //全部
        if (StringUtils.isEmpty(funcCode)) {
            //微服务环境下不允许获取所有bage
            return DirectJsonResult.buildObjectResult("{}");
            //单个
        }

        DynaBean one = metaService.selectOne("JE_CORE_MENU",
                ConditionsWrapper.builder().apply("MENU_NODEINFO LIKE {0}  AND MENU_BADGE='1'", funcCode + "%"));
        if (one != null) {
            list.add(one);
        }
        //数字提醒
        JSONObject badges = new JSONObject();
        //加和菜单提醒
        JSONObject menus = new JSONObject();
        for (DynaBean menu : list) {
            String badgeInfo = menu.getStr("MENU_BADGEINFO");
            String id = menu.getPkValue();
            String badgeCls = menu.getStr("MENU_BADGECLS");
            String badgeBgColor = menu.getStr("MENU_BADGEBGCOLOR");
            String badgeColor = menu.getStr("MENU_BADGECOLOR");
            String badgeType = menu.getStr("MENU_BADGETYPE");
            String badgeLoad = menu.getStr("MENU_BADGELOAD");
            JSONObject badge = new JSONObject();
            badge.put("id", id);
            badge.put("cls", badgeCls);
            String style = "";
            if ("idit".equals(badgeCls)) {
                if (StringUtils.isNotBlank(badgeColor)) {
                    style += "color:" + badgeColor + ";";
                }
                if (StringUtils.isNotBlank(badgeBgColor)) {
                    style += "background-color:" + badgeBgColor + ";";
                }
            }
            badge.put("style", style);
            //功能load时，用于判断是否启用数字提醒
            if ("MT".equals(menu.getStr("MENU_NODEINFOTYPE"))) {
                badge.put("load", "load".equals(badgeLoad));
                badge.put("funcCode", menu.getStr("MENU_NODEINFO").split(",")[0]);
            }

            //计算数字
            if ("menu".equals(badgeType)) {
                menus.put(id, badgeInfo);
                badge.put("menus", badgeInfo);
            } else if ("sql".equals(badgeType)) {
                Set<Map.Entry<String, Object>> ddSet = new HashSet();
                //加入登录信息
                ddSet.addAll(SecurityUserHolder.getCurrentInfo().entrySet());
                String sql = StringUtil.parseKeyWordWithObject(badgeInfo, ddSet);
                int num = 0;
                if (StringUtil.isNotEmpty(sql)) {
                    num = new Long(metaService.countBySql(sql)).intValue();
                }
                badge.put("num", num);
            } else if ("action".equals(badgeType)) {
                String beanName = "";
                String methedName = "";
                if (badgeInfo.split(",").length > 1) {
                    beanName = badgeInfo.split(",")[0];
                    methedName = badgeInfo.split(",")[1];
                }
                long num = 0;
                //调用自定义action方法...
                if (StringUtil.isNotEmpty(beanName) && StringUtil.isNotEmpty(methedName)) {
                    Object bean = SpringContextHolder.getBean(beanName);
                    num = (Long) ReflectionUtils.getInstance().invokeMethod(bean, methedName, new Object[]{});
                }
                badge.put("num", num);
            }
            badges.put(id, badge);
        }

        //加和菜单计算
        for (Iterator<String> i = menus.keySet().iterator(); i.hasNext(); ) {
            String id = i.next();
            String[] mIds = menus.getString(id).split(",");
            int num = 0;
            for (String mid : mIds) {
                if (badges.containsKey(mid)) {
                    JSONObject item = badges.getJSONObject(mid);
                    JSONArray parent = new JSONArray();
                    if (item.containsKey("parent")) {
                        parent = item.getJSONArray("parent");
                    }
                    parent.add(id);
                    item.put("parent", parent);
                    num += item.getInteger("num");
                }
            }
            badges.getJSONObject(id).put("num", num);
        }
        return badges;
    }

    @Override
    public BaseRespResult doDevelopPerm(String pkValue) {
        //todo 重新开发
        return BaseRespResult.errorResult("请重新开发！");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int updateTopMenuRelation(String menuId, String topMenuIds, String topMenuNames) {
        if (Strings.isNullOrEmpty(menuId)) {
            return 0;
        }
        DynaBean menuBean = metaService.selectOne("JE_CORE_MENU", ConditionsWrapper.builder().eq("JE_CORE_MENU_ID", menuId));
        //如果topMenuId为空 则同步清空 关联顶部菜单字段
        if (Strings.isNullOrEmpty(topMenuIds)) {
            doRemoveAllHeadMenuRelation(menuId);
            return updateTopMenuRelationBean(menuId, topMenuIds, topMenuNames);
        }
        String oldTopMenuId = menuBean.getStr("MENU_LINK_TOPMENU_ID", "");
        List<String> addHeadMenuRelation = new ArrayList<>();
        List<String> deleteHeadMenuRelation = new ArrayList<>();

        // 查找需要添加的数据
        String[] newTopMenuIdArray = topMenuIds.split(",");

        for (int i = 0; i < newTopMenuIdArray.length; i++) {
            String topMenuId = newTopMenuIdArray[i];
            if (!oldTopMenuId.contains(topMenuId)) {
                addHeadMenuRelation.add(topMenuId);
            }
        }

        // 查找需要删除的数据
        if (!Strings.isNullOrEmpty(oldTopMenuId)) {
            String[] oldTopMenuIdArray = oldTopMenuId.split(",");
            for (String topMenuId : oldTopMenuIdArray) {
                if (!topMenuIds.contains(topMenuId)) {
                    deleteHeadMenuRelation.add(topMenuId);
                }
            }
        }

        for (String delId : new ArrayList<>(deleteHeadMenuRelation)) {
            doRemoveHeadMenuRelation(menuId, delId);
        }

        for (String addId : addHeadMenuRelation) {
            List<Map<String, Object>> countList = metaService.selectSql("SELECT MAX(SY_ORDERINDEX) AS MAX_COUNT FROM JE_RBAC_HEADMENU_RELATION WHERE JE_RBAC_HEADMENU_ID ={0}", addId);
            int count = 0;
            if (countList.size() > 0) {
                count = (int) countList.get(0).get("MAX_COUNT");
            }
            DynaBean headMenuRelationBean = new DynaBean("JE_RBAC_HEADMENU_RELATION", false);
            headMenuRelationBean.set("JE_RBAC_HEADMENU_RELATION_ID", JEUUID.uuid());
            headMenuRelationBean.set("RELATION_MENUMODULE_ID", menuBean.getStr("JE_CORE_MENU_ID"));
            headMenuRelationBean.set("RELATION_MENUMODULE_NAME", menuBean.getStr("MENU_MENUNAME"));
            headMenuRelationBean.set("SY_PRODUCT_ID", menuBean.getStr("SY_PRODUCT_ID"));
            headMenuRelationBean.set("SY_PRODUCT_NAME", menuBean.getStr("SY_PRODUCT_NAME"));
            headMenuRelationBean.set("JE_RBAC_HEADMENU_ID", addId);
            headMenuRelationBean.set("SY_ORDERINDEX", count + 1);
            headMenuRelationBean.set("SY_STATUS", "1");
            commonService.buildModelCreateInfo(headMenuRelationBean);
            metaService.insert(headMenuRelationBean);
        }

        return updateTopMenuRelationBean(menuId, topMenuIds, topMenuNames);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void syncUpdateUserRolePermByProductId(DynaBean dynaBean) {
        //（1）查询该菜单是否发生 方案类和平台类产品的切换
        DynaBean sourceBean = findById(dynaBean.getStr("JE_CORE_MENU_ID"));
        DynaBean sourceProductBean = metaResourceService.selectOneByNativeQuery("JE_PRODUCT_MANAGE", NativeQuery.build()
                .eq("JE_PRODUCT_MANAGE_ID", sourceBean.getStr("SY_PRODUCT_ID")));
        if (!sourceBean.getStr("SY_PRODUCT_ID").equals(dynaBean.getStr("SY_PRODUCT_ID"))) {
            //若不一致，则判断是否发生切换
            //判断当前所属产品，若是方案类，则查开发者类型角色是否 与之关联，若关联-则清除
            DynaBean productBean = metaResourceService.selectOneByNativeQuery("JE_PRODUCT_MANAGE", NativeQuery.build()
                    .eq("JE_PRODUCT_MANAGE_ID", dynaBean.getStr("SY_PRODUCT_ID")));
            if (productBean != null) {
                //判断当前所属产品，若是平台类，则查普通类型角色是否 与之关联，若关联-则清除
                if (!productBean.getStr("PRODUCT_TYPE").equals(sourceProductBean.getStr("PRODUCT_TYPE"))) {
                    doRemovMenuPermRelation(dynaBean.getStr("JE_CORE_MENU_ID"));
                }
            }
        }
    }

    @Transactional(rollbackFor = RuntimeException.class)
    public void doRemovMenuPermRelation(String menuIds) {
        List<String> menuIdList = Splitter.on(",").splitToList(menuIds);
        List<DynaBean> menus = metaService.select("JE_CORE_MENU", ConditionsWrapper.builder().in("JE_CORE_MENU_ID", menuIdList));
        List<String> funcCodeList = new ArrayList<>();
        List<String> permCodeList = new ArrayList<>();
        for (DynaBean menu : menus) {
//            if (isLog()) {
//                developLogRpcService.doDevelopLog("DELETE", "删除", "MENU", "菜单", menu.getStr("MENU_MENUNAME"), menu.getStr("MENU_CODE"), menu.getStr("JE_CORE_MENU_ID"));
//            }
            if ("MT".equals(menu.getStr("MENU_NODEINFOTYPE"))) {
                funcCodeList.add(menu.getStr("MENU_NODEINFO"));
            } else {
                if (!Strings.isNullOrEmpty(menu.getStr("MENU_NODEINFO"))) {
                    permCodeList.add(pcPluginBaseService.formatPcPluginShowTemplate(menu.getStr("MENU_NODEINFO")));
                    permCodeList.add(pcPluginBaseService.formatPcPluginConfigTemplate(menu.getStr("MENU_NODEINFO")));
                }
            }
            permCodeList.add(pcMenuDataService.formatMenuDataShowTemplate(menu.getStr("JE_CORE_MENU_ID")));
            permCodeList.add(pcMenuDataService.formatMenuDataUpdateTemplate(menu.getStr("JE_CORE_MENU_ID")));
            permCodeList.add(pcMenuDataService.formatMenuDataDeleteTemplate(menu.getStr("JE_CORE_MENU_ID")));

            //级联删除顶部菜单关联表的菜单数据
//            if(!Strings.isNullOrEmpty(menu.getStr("MENU_LINK_TOPMENU_ID"))){
//                menuService.doRemoveHeadMenuRelation(menu.getStr("JE_CORE_MENU_ID"),menu.getStr("MENU_LINK_TOPMENU_ID"));
//            }
        }

        List<String> permIdList = new ArrayList<>();
        //功能
        Map<String, List<DynaBean>> funcResult = metaFuncRpcService.findPermedFuncsAndChildFuncsWithButtonsByFuncCodes(funcCodeList);
        List<DynaBean> funcList = new ArrayList<>();
        funcList.addAll(funcResult.get("main"));
        funcList.addAll(funcResult.get("child"));
        List<DynaBean> funcButtonList = funcResult.get("button") == null ? new ArrayList<>() : funcResult.get("button");

        for (DynaBean eachFuncBean : funcList) {
            //功能权限
            permCodeList.add(pcFuncBaseService.formatPcFuncShowTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE")));
            permCodeList.add(pcFuncBaseService.formatPcFuncConfigTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE")));
            permCodeList.add(pcFuncBaseService.formatPcFuncUpdateTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE")));
            permCodeList.add(pcFuncBaseService.formatPcFuncDeleteTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE")));
            //设置功能按钮的权限
            for (DynaBean eachButtonBean : funcButtonList) {
                if (eachFuncBean.getStr("JE_CORE_FUNCINFO_ID").equals(eachButtonBean.getStr("RESOURCEBUTTON_FUNCINFO_ID"))) {
                    permCodeList.add(pcFuncButtonService.formatPcFuncButtonShowTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE"), eachButtonBean.getStr("RESOURCEBUTTON_CODE")));
                    permCodeList.add(pcFuncButtonService.formatPcFuncButtonUpdateTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE"), eachButtonBean.getStr("RESOURCEBUTTON_CODE")));
                    permCodeList.add(pcFuncButtonService.formatPcFuncButtonDeleteTemplate(eachFuncBean.getStr("FUNCINFO_FUNCCODE"), eachButtonBean.getStr("RESOURCEBUTTON_CODE")));
                }
            }
        }

        if (!permCodeList.isEmpty()) {
            List<DynaBean> permissionList = metaService.select("JE_RBAC_PERM", ConditionsWrapper.builder()
                    .in("PERM_CODE", permCodeList));
            for (DynaBean eachPluginPermission : permissionList) {
                if (!permIdList.contains(eachPluginPermission.getStr("JE_RBAC_PERM_ID"))) {
                    permIdList.add(eachPluginPermission.getStr("JE_RBAC_PERM_ID"));
                }
            }
        }

        if (!permIdList.isEmpty()) {
            metaService.delete("JE_RBAC_ROLEPERM", ConditionsWrapper.builder().in("JE_RBAC_PERM_ID", permIdList));
            metaService.delete("JE_RBAC_DEPTPERM", ConditionsWrapper.builder().in("JE_RBAC_PERM_ID", permIdList));
            metaService.delete("JE_RBAC_USERPERM", ConditionsWrapper.builder().in("JE_RBAC_PERM_ID", permIdList));
            metaService.delete("JE_RBAC_PERMGROUPPERM", ConditionsWrapper.builder().in("JE_RBAC_PERM_ID", permIdList));
            metaService.delete("JE_RBAC_ORGPERM", ConditionsWrapper.builder().in("JE_RBAC_PERM_ID", permIdList));
        }
        accountPermissionCache.clear();
        accountProductCache.clear();
        funcPermissionCache.clear();
//        return metaService.delete("JE_CORE_MENU", ConditionsWrapper.builder().in("JE_CORE_MENU_ID", Splitter.on(",").splitToList(menuIds)));
    }

    public Boolean checkMenuConfigInfo(DynaBean dynaBean) throws MenuException {
        long count = 0;
        if (Strings.isNullOrEmpty(dynaBean.getStr("JE_CORE_MENU_ID"))) {
            count = metaService.countBySql(ConditionsWrapper.builder().table("JE_CORE_MENU").eq("MENU_NODEINFO", dynaBean.getStr("MENU_NODEINFO")));
        } else {
            count = metaService.countBySql(ConditionsWrapper.builder().apply("SELECT * FROM JE_CORE_MENU WHERE JE_CORE_MENU_ID != {0} AND (MENU_NODEINFO = {1})", dynaBean.getStr("JE_CORE_MENU_ID"), dynaBean.getStr("MENU_NODEINFO")));
        }
        if (count > 0) {
            return false;
        }
        return true;
    }

    public Boolean checkFunCode(String menuModeInfo) {
        List<DynaBean> funbeanList = metaResourceService.selectByTableCodeAndNativeQuery("JE_CORE_FUNCINFO", NativeQuery.build().eq("FUNCINFO_FUNCCODE", menuModeInfo));
        if (funbeanList != null && funbeanList.size() > 0) {
            return true;
        }
        return false;
    }

    @Override
    public void checkFunCodeData(DynaBean dynaBean) throws MenuException {
        if (("MT".equals(dynaBean.getStr("MENU_NODEINFOTYPE")) || "DIC".equals(dynaBean.getStr("MENU_NODEINFOTYPE")))) {
            //校验功能编码不能为空，若存在则判断菜单是否重复。
            if (Strings.isNullOrEmpty(dynaBean.getStr("MENU_NODEINFO"))) {
                throw new MenuException("配置信息不能为空，请检查！");
            }
            //判断是否存在
//            if(!checkFunCode(dynaBean.getStr("MENU_NODEINFO"))){
//                throw new MenuException("功能编码不存在，请检查！");
//            }
            if (!checkMenuConfigInfo(dynaBean)) {
                throw new MenuException("该功能已被使用，请检查！");
            }
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int doRemoveHeadMenuRelation(String menuId, String topMenuId) {
        return metaService.delete("JE_RBAC_HEADMENU_RELATION", ConditionsWrapper.builder().eq("RELATION_MENUMODULE_ID", menuId).eq("JE_RBAC_HEADMENU_ID", topMenuId));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int doRemoveAllHeadMenuRelation(String menuId) {
        return metaService.delete("JE_RBAC_HEADMENU_RELATION", ConditionsWrapper.builder().eq("RELATION_MENUMODULE_ID", menuId));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int doRemoveHeadMenuRelationByTopMenuId(String topMenuId) {
        return metaService.delete("JE_RBAC_HEADMENU_RELATION", ConditionsWrapper.builder().eq("JE_RBAC_HEADMENU_ID", topMenuId));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public int updateTopMenuRelationBean(String menuId, String topMenuId, String topMenuName) {
        return metaService.executeSql("UPDATE JE_CORE_MENU SET MENU_LINK_TOPMENU_ID ={0},MENU_LINK_TOPMENU_NAME={1} WHERE JE_CORE_MENU_ID ={2}", topMenuId, topMenuName, menuId);
    }

    @Override
    public DynaBean findById(String menuId) {
        return metaService.selectOne("JE_CORE_MENU", ConditionsWrapper.builder().eq("JE_CORE_MENU_ID", menuId));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void checkAndUpdate(DynaBean sourceBean, DynaBean moveAfterBean) {
        if ("ROOT".equals(sourceBean.getStr("SY_PARENT"))
                && !"ROOT".equals(moveAfterBean.getStr("SY_PARENT"))
                && !Strings.isNullOrEmpty(moveAfterBean.getStr("MENU_LINK_TOPMENU_ID"))) {
            //清除与顶部菜单关联关系
            metaService.executeSql("UPDATE JE_CORE_MENU SET MENU_LINK_TOPMENU_ID={0},MENU_LINK_TOPMENU_NAME={1} WHERE JE_CORE_MENU_ID ={2}", "", "", sourceBean.getStr("JE_CORE_MENU_ID"));
            metaService.delete("JE_RBAC_HEADMENU_RELATION", ConditionsWrapper.builder().eq("RELATION_MENUMODULE_ID", sourceBean.getStr("JE_CORE_MENU_ID")));
        }
    }

    @Override
    public List<Map<String, Object>> getCommonMenuByPlan(String plan) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        ConditionsWrapper wrapper = ConditionsWrapper.builder();
        wrapper.table("JE_CORE_MENU");
        wrapper.eq("MENU_QUICKSTART", "1");
        if (!Strings.isNullOrEmpty(plan)) {
            //过滤，必须有一级菜单才加载一级菜单下的收藏菜单
            DynaBean planBean = metaResourceService.selectOneByNativeQuery("JE_CORE_SETPLAN", NativeQuery.build().eq("JE_SYS_PATHSCHEME", plan));
            String topMenuId = planBean.getStr("SETPLAN_ASSOCIATE_TOP_MENU_ID");
            String isAssociateAllTopMenu = planBean.getStr("SETPLAN_ASSOCIATE_ALL_TOP_MENU", "1");
            if (!Strings.isNullOrEmpty(topMenuId) && !isAssociateAllTopMenu.equals("1")) {
                List<DynaBean> headmenu_relation = metaService.select("JE_RBAC_HEADMENU_RELATION",
                        ConditionsWrapper.builder().in("JE_RBAC_HEADMENU_ID", Splitter.on(",").splitToList(topMenuId)), "RELATION_MENUMODULE_ID");
                //如果没有查到一级模块，并且方案存在顶部菜单id，说明只有插件，只有插件的情况下，快捷菜单一个都不展示
                if (headmenu_relation.size() == 0 && !Strings.isNullOrEmpty(topMenuId)) {
                    return resultList;
                }
                wrapper.and(inWrapper -> {
                    for (int i = 0; i < headmenu_relation.size(); i++) {
                        if (i > 0) {
                            inWrapper.or();
                        }
                        inWrapper.like("SY_PATH", headmenu_relation.get(i).getStr("RELATION_MENUMODULE_ID"));
                    }
                });
            }
        }
        wrapper.orderByAsc("SY_TREEORDERINDEX");
        List<Map<String, Object>> dynaBeanList = metaService.selectSql(wrapper);
        //权限过滤
        String departmentId = SecurityUserHolder.getCurrentAccountDepartment().getId();
        String accountId = SecurityUserHolder.getCurrentAccountId();
        boolean enableSaas = SpringContextHolder.getBean("enableSaas");
        String tenantId = "";
        if (enableSaas) {
            tenantId = SecurityUserHolder.getCurrentAccountTenantId();
        }
        List<String> menuPermissionList = permissionRpcService.findAccountMenuPermissions(departmentId, accountId, tenantId);
        for (Map<String, Object> menu : dynaBeanList) {
            if (menuPermissionList.contains(pcMenuDataService.formatMenuDataShowTemplate(menu.get("JE_CORE_MENU_ID").toString()))) {
                resultList.add(menu);
            }
        }
        return resultList;
    }

    @Override
    public JSONObject getMenuScheme(String id) {
        JSONObject result = new JSONObject();
        result.put("perm", false);
        result.put("plans", new ArrayList<>());

        if (!checkMenyPermByMenuId(id)) {
            return result;
        }
        result.put("perm", true);
        List<String> topMenuIds = new ArrayList<>();

        DynaBean topMenuBean = metaService.selectOneByPk("JE_RBAC_HEADMENU", id);
        if (topMenuBean != null) {
            topMenuIds.add(topMenuBean.getPkValue());
        } else {
            DynaBean menuInfo = metaService.selectOneByPk("je_core_menu", id);
            String path = menuInfo.getStr("SY_PATH");
            if (Strings.isNullOrEmpty(path)) {
                return result;
            }

            String[] paths = path.split("/");
            if (paths.length < 2) {
                return result;
            }

            String modelId = paths[1];

            String sql = "SELECT * FROM JE_RBAC_HEADMENU WHERE " +
                    "JE_RBAC_HEADMENU_ID IN (SELECT JE_RBAC_HEADMENU_ID FROM " +
                    "JE_RBAC_HEADMENU_RELATION WHERE RELATION_MENUMODULE_ID={0}) AND HEADMENU_TYPE_CODE='MENU'";
            List<Map<String, Object>> list = metaService.selectSql(sql, modelId);
            for (Map<String, Object> map : list) {
                topMenuIds.add(map.get("JE_RBAC_HEADMENU_ID").toString());
            }
        }

        NativeQuery nativeQuery = NativeQuery.build();
        String column = "SETPLAN_ASSOCIATE_TOP_MENU_ID";
        nativeQuery.addCondition(new Condition(column, ConditionEnum.IS_NULL.getType(), null, "or"));
        nativeQuery.addCondition(new Condition(column, ConditionEnum.EQ.getType(), "", "or"));
        nativeQuery.addCondition(new Condition(column, ConditionEnum.IN.getType(), topMenuIds, "or"));
        List<DynaBean> planBeans = metaResourceService.selectByTableCodeAndNativeQuery("JE_CORE_SETPLAN", nativeQuery);
        List<String> plans = new ArrayList<>();
        for (DynaBean dynaBean : planBeans) {
            plans.add(dynaBean.getStr("JE_SYS_PATHSCHEME"));
        }
        result.put("plans", plans);
        return result;
    }

    private boolean checkMenyPermByMenuId(String id) {
        String departmentId = SecurityUserHolder.getCurrentAccountDepartment().getId();
        String accountId = SecurityUserHolder.getCurrentAccountId();
        boolean enableSaas = SpringContextHolder.getBean("enableSaas");
        String tenantId = "";
        if (enableSaas) {
            tenantId = SecurityUserHolder.getCurrentAccountTenantId();
        }
        //如果是顶部菜单
        DynaBean topMenuBean = metaService.selectOneByPk("JE_RBAC_HEADMENU", id);
        if (topMenuBean != null) {
            List<String> accountTopMenuPermissions = permissionRpcService.findAccountTopMenuPermissions(departmentId, accountId, tenantId);
            if ("0".equals(topMenuBean.getStr("HEADMENU_PUBLIC_CODE")) && !accountTopMenuPermissions.contains(topMenuDataService.formatTopMenuShowTemplate(id))) {
                return false;
            } else {
                return true;
            }
        }
        //功能菜单
        List<String> menuPermissionList = permissionRpcService.findAccountMenuPermissions(departmentId, accountId, tenantId);
        if (menuPermissionList.contains(pcMenuDataService.formatMenuDataShowTemplate(id))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 是否记录日志
     *
     * @return
     */
    private Boolean isLog() {
        if ("1".equals(systemSettingRpcService.findSettingValue(JE_SYS_DEVELOPLOG))) {
            return true;
        }
        return false;
    }

    /**
     * 初始化产品字段信息
     *
     * @param dynaBean 业务bean
     */
    private void buildProductInfo(DynaBean dynaBean) {
        String productId = dynaBean.getStr(SY_PRODUCT_ID);
        if (Strings.isNullOrEmpty(productId)) {
            throw new PlatformException("产品信息为空，请先选择产品！", PlatformExceptionEnum.JE_CORE_ENEITY_SAVE_ERROR);
        }
        DynaBean product = productRpcService.getInfoById(dynaBean.getStr(SY_PRODUCT_ID));
        if (product == null) {
            throw new PlatformException("产品信息不存在，保存失败！", PlatformExceptionEnum.JE_CORE_ENEITY_SAVE_ERROR);
        }
        dynaBean.setStr(SY_PRODUCT_CODE, product.getStr("PRODUCT_CODE"));
        dynaBean.setStr(SY_PRODUCT_NAME, product.getStr("PRODUCT_NAME"));
    }

}
